// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin 1746365080@qq.com
 * @Date: 2024-11-04 15:15:27
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2024-12-23 14:56:08
 * @FilePath: /SGSim/Import/BDFImport/BulkData/PARAMETER/NLPARMParser.cpp
 */
#include "NLPARMParser.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <map>

#include <boost/algorithm/string.hpp>

#include "Utility/Logging/SGLogger.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Parameter/INLPARMService.h"

#include "Import/BDFImport/BDFParserBase.h"
BULKDATA_ENTRY_PARSER_REG (NLPARM);
/*
// file://./../../Doc/MarkDown/BulkData/NLPARM/NLPARM.md>
*/

using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::DataStructure;
// 以下需要修改
#include <cstdint>

enum NLPARMKey : std::uint8_t
{
    NLPARMKEY_ID      = 2,   //
    NLPARMKEY_NINC    = 3,   // 增量数量
    NLPARMKEY_DT      = 4,   // 蠕变分析的增量时间间隔
    NLPARMKEY_KMETHOD = 5,   // 控制刚度更新的方法
    NLPARMKEY_KSTEP   = 6,   // 在ITER方法中，刚度更新之前的迭代次数，FNT和PFNT中还不一样
    NLPARMKEY_MAXITER = 7,   // 每个加载增量的迭代次数限制
    NLPARMKEY_CONV    = 8,   // 选择收敛标准的标志
    NLPARMKEY_INTOUT  = 9,   // 中间输出标志

    NLPARMKEY_EPSU    = 12,  // 位移（U）标准的误差容忍度
    NLPARMKEY_EPSP    = 13,  // 载荷（P）标准的误差容忍度
    NLPARMKEY_EPSW    = 14,  // 功（W）标准的误差容忍度
    NLPARMKEY_MAXDIV  = 15,  // 每次迭代的可能发散条件限制
    NLPARMKEY_MAXQN   = 16,  // 可保存到数据库中的准牛顿修正向量的最大数量
    NLPARMKEY_MAXLS   = 17,  // 每次迭代允许的最大线搜索次数。
    NLPARMKEY_FSTRESS = 18,  // 用于限制材料例程中子增量大小的有效应力的分数
    NLPARMKEY_LSTOL   = 19,  // 线搜索容差

    // 其他字段位置的标识符
    NLPARMKEY_MAXBIS  = 22,  // 每个加载增量允许的最大二分次数
    NLPARMKEY_MAXR    = 26,  // 调整后的弧长增量与初始值的最大比率。
    NLPARMKEY_RTOLB   = 28,  // 每次迭代允许的最大增量旋转（以度为单位），以激活二分法
    NLPARMKEY_MINITER = 29   // 每个增量的最小迭代次数，仅适用于具有接触的SOL 101和SOL 400
};

namespace
{
    Common::I64 getKMETHOD (const std::string& KMETHODKey)
    {
        static std::map<std::string, Common::I64> KMETHODmap = {
            { "AUTO", 1 }, { "ITER", 2 }, { "SEMI", 4 }, { "FNT ", 2 }, { "PFNT", 1 },
        };
        auto iter = KMETHODmap.find (KMETHODKey);
        if (iter != KMETHODmap.end ())
        {
            return KMETHODmap[KMETHODKey];
        }
        return 1;
    }
    // TODO(bug 001) 默认值条件很多，有待补充
    Common::I64 getCONV (const std::string& CONVKey)
    {
        static std::map<std::string, Common::I64> CONVmap = {
            { "PW", -1 },
        };

        auto iter = CONVmap.find (CONVKey);
        if (iter != CONVmap.end ())
        {
            return CONVmap[CONVKey];
        }
        return -1;
    }
    Common::I64 getINTOUT (const std::string& INTOUTKey)
    {
        static std::map<std::string, Common::I64> INTOUTmap = {
            { "NO", 0 },
            { "YES", 1 },
            { "ALL", 2 },
        };
        auto iter = INTOUTmap.find (INTOUTKey);
        if (iter != INTOUTmap.end ())
        {
            return INTOUTmap[INTOUTKey];
        }
        return -1;
    }

}  // namespace

SG::DataStructure::Common::Status BDF::BULKDATA::ParseNLPARM (const std::shared_ptr<DBServiceFactory>& dbServiceFactory,
                                                              std::vector<std::string>&                dividedEntryInfo)
{
    // 创建临时节点数据结构，默认值为0
    SG::DataStructure::FEM::NLPARMData tempData;

    // TODO(bug 001) m_dominId的正确填写
    tempData.m_domainId = 1;

    int curIDKey = 1;  // 当前字符串是第几项
    // TODO(bug 001) 默认值条件很多，有待补充
    // 遍历分割后的每个词条
    for (std::string& curStrKey : dividedEntryInfo)
    {
        // 检查当前字符串是否为空白
        bool const isEmpty = is_all_space (curStrKey);
        if (isEmpty)
        {
            switch (curIDKey)
            {
            case NLPARMKEY_KMETHOD:
                curStrKey = "AUTO";
                ;
                break;
            case NLPARMKEY_CONV:
                curStrKey = "PW";
                ;
                break;
            case NLPARMKEY_INTOUT:
                curStrKey = "NO";
                ;
                break;
            default:
                curIDKey++;
                continue;
                break;
            }
        }

        // 根据当前词条的位置进行相应的解析
        switch (curIDKey)
        {
        case NLPARMKEY_ID:
            tempData.m_id = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_NINC:
            tempData.m_NINC = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_DT:
            tempData.m_DT = convertToReal (curStrKey);
            break;
        case NLPARMKEY_KMETHOD:
            boost::trim (curStrKey);
            tempData.m_KMETHOD = getKMETHOD (curStrKey);
            break;
        case NLPARMKEY_KSTEP:
            tempData.m_KSTEP = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_MAXITER:
            tempData.m_MAXITER = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_CONV:
            boost::trim (curStrKey);
            tempData.m_CONV = getCONV (curStrKey);
            break;
        case NLPARMKEY_INTOUT:
            boost::trim (curStrKey);
            tempData.m_INTOUT = getINTOUT (curStrKey);
            break;
        case NLPARMKEY_EPSU:
            tempData.m_EPSU = convertToReal (curStrKey);
            break;
        case NLPARMKEY_EPSP:
            tempData.m_EPSP = convertToReal (curStrKey);
            break;
        case NLPARMKEY_EPSW:
            tempData.m_EPSW = convertToReal (curStrKey);
            break;
        case NLPARMKEY_MAXDIV:
            tempData.m_MAXDIV = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_MAXQN:
            tempData.m_MAXQN = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_MAXLS:
            tempData.m_MAXLS = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_FSTRESS:
            tempData.m_FSTRESS = convertToReal (curStrKey);
            break;
        case NLPARMKEY_LSTOL:
            tempData.m_LSTOL = convertToReal (curStrKey);
            break;
        case NLPARMKEY_MAXBIS:
            tempData.m_MAXBIS = convertToI64 (curStrKey);
            break;
        case NLPARMKEY_MAXR:
            tempData.m_MAXR = convertToReal (curStrKey);
            break;
        case NLPARMKEY_RTOLB:
            tempData.m_RTOLB = convertToReal (curStrKey);
            break;
        case NLPARMKEY_MINITER:
            tempData.m_MINITER = convertToI64 (curStrKey);
            break;
        default:
            break;
        }

        // 处理完当前词条后，移动到下一个词条
        curIDKey++;
    }
    // 将解析完成的节点数据添加到数据库服务中
    return dbServiceFactory->get<INLPARMService> ()->Add (tempData);
}